package com.xuan.utils.xuan.bazi;

import com.nlf.calendar.EightChar;
import com.nlf.calendar.JieQi;
import com.nlf.calendar.Lunar;
import com.nlf.calendar.Solar;
import com.nlf.calendar.eightchar.DaYun;
import com.nlf.calendar.eightchar.LiuNian;
import com.nlf.calendar.eightchar.Yun;
import com.xuan.utils.common.CommonUtil;
import com.xuan.utils.common.DateUtil;
import com.xuan.utils.xuan.bazi.utils.BaZiShenShaUtil;
import lombok.Getter;

import java.util.*;

/**
 * 八字
 *
 * @author 善待
 */
@Getter
public class BaZi {

    /**
     * 姓名
     */
    private String name;

    /**
     * 性别（男。女）
     */
    private String sex;

    /**
     * 乾造\坤造
     */
    private String zao;

    /**
     * 占事
     */
    private String occupy;

    /**
     * 地区
     */
    private String address;

    /**
     * 日期
     */
    private Date date;

    /**
     * 公历日期
     */
    private Solar solar;

    /**
     * 农历日期
     */
    private Lunar lunar;

    /**
     * 星期
     */
    private String week;

    /**
     * 季节
     */
    private String season;

    /**
     * 生肖
     */
    private String zodiac;

    /**
     * 星座
     */
    private String constellation;

    /**
     * 月相
     */
    private String yueXiang;
    /**
     * 月将
     */
    private String yueJiang;
    /**
     * 月将神
     */
    private String yueJiangShen;

    /**
     * 八字
     */
    private List<String> baZi;
    /**
     * 八字五行
     */
    private List<String> baZiWuXing;
    /**
     * 八字空亡
     */
    private List<String> baZiKongWang;
    /**
     * 八字纳音
     */
    private List<String> baZiNaYin;

    /**
     * 年干
     */
    private String yearGan;
    /**
     * 月干
     */
    private String monthGan;
    /**
     * 日干
     */
    private String dayGan;
    /**
     * 时干
     */
    private String hourGan;

    /**
     * 年干支主星
     */
    private String yearGanZhiZhuXing;
    /**
     * 月干支主星
     */
    private String monthGanZhiZhuXing;
    /**
     * 日干支主星
     */
    private String dayGanZhiZhuXing;
    /**
     * 时干支主星
     */
    private String hourGanZhiZhuXing;

    /**
     * 年支
     */
    private String yearZhi;
    /**
     * 月支
     */
    private String monthZhi;
    /**
     * 日支
     */
    private String dayZhi;
    /**
     * 时支
     */
    private String hourZhi;

    /**
     * 年干支
     */
    private String yearGanZhi;
    /**
     * 月干支
     */
    private String monthGanZhi;
    /**
     * 日干支
     */
    private String dayGanZhi;
    /**
     * 时干支
     */
    private String hourGanZhi;

    /**
     * 年干五行
     */
    private String yearGanWuXing;
    /**
     * 月干五行
     */
    private String monthGanWuXing;
    /**
     * 日干五行
     */
    private String dayGanWuXing;
    /**
     * 时干五行
     */
    private String hourGanWuXing;

    /**
     * 年支五行
     */
    private String yearZhiWuXing;
    /**
     * 月支五行
     */
    private String monthZhiWuXing;
    /**
     * 日支五行
     */
    private String dayZhiWuXing;
    /**
     * 时支五行
     */
    private String hourZhiWuXing;

    /**
     * 年干支五行
     */
    private String yearGanZhiWuXing;
    /**
     * 月干支五行
     */
    private String monthGanZhiWuXing;
    /**
     * 日干支五行
     */
    private String dayGanZhiWuXing;
    /**
     * 时干支五行
     */
    private String hourGanZhiWuXing;

    /**
     * 年支藏干
     */
    private List<String> yearZhiCangGan;
    /**
     * 月支藏干
     */
    private List<String> monthZhiCangGan;
    /**
     * 日支藏干
     */
    private List<String> dayZhiCangGan;
    /**
     * 时支藏干
     */
    private List<String> hourZhiCangGan;

    /**
     * 年干支副星
     */
    private List<String> yearGanZhiFuXing;
    /**
     * 月干支副星
     */
    private List<String> monthGanZhiFuXing;
    /**
     * 日干支副星
     */
    private List<String> dayGanZhiFuXing;
    /**
     * 时干支副星
     */
    private List<String> hourGanZhiFuXing;

    /**
     * 年干支地势
     */
    private String yearGanZhiDiShi;
    /**
     * 月干支地势
     */
    private String monthGanZhiDiShi;
    /**
     * 日干支地势
     */
    private String dayGanZhiDiShi;
    /**
     * 时干支地势
     */
    private String hourGanZhiDiShi;

    /**
     * 年干支空亡
     */
    private String yearGanZhiKongWang;
    /**
     * 月干支空亡
     */
    private String monthGanZhiKongWang;
    /**
     * 日干支空亡
     */
    private String dayGanZhiKongWang;
    /**
     * 时干支空亡
     */
    private String hourGanZhiKongWang;

    /**
     * 年干支纳音
     */
    private String yearGanZhiNaYin;
    /**
     * 月干支纳音
     */
    private String monthGanZhiNaYin;
    /**
     * 日干支纳音
     */
    private String dayGanZhiNaYin;
    /**
     * 时干支纳音
     */
    private String hourGanZhiNaYin;

    /**
     * 年干支神煞
     */
    private List<String> yearGanZhiShenSha;
    /**
     * 月干支神煞
     */
    private List<String> monthGanZhiShenSha;
    /**
     * 日干支神煞
     */
    private List<String> dayGanZhiShenSha;
    /**
     * 时干支神煞
     */
    private List<String> hourGanZhiShenSha;
    /**
     * 小儿关煞
     */
    private List<String> xiaoErGuanSha;

    /**
     * 天干留意
     */
    private List<String> tianGanLiuYi;
    /**
     * 地支留意
     */
    private List<String> diZhiLiuYi;

    /**
     * 起运
     */
    private String qiYun;
    /**
     * 起运日期
     */
    private String qiYunDate;
    /**
     * 人元司令分野
     */
    private String renYuan;

    /**
     * 出生节气
     */
    private String birthSolarTerms;

    /**
     * 上一节气
     */
    private String prevJieQi;
    /**
     * 上一节气日期
     */
    private String prevJieQiDate;
    /**
     * 距上一节气天数
     */
    private int prevJieQiDayNumber;

    /**
     * 下一节气
     */
    private String nextJieQi;
    /**
     * 下一节气日期
     */
    private String nextJieQiDate;
    /**
     * 距下一节气天数
     */
    private int nextJieQiDayNumber;

    /**
     * 星宿
     */
    private String xingXiu;
    /**
     * 星宿吉凶
     */
    private String xiuJiXiong;
    /**
     * 星宿吉凶歌诀
     */
    private String xiuJiXiongGeJue;

    /**
     * 胎元
     */
    private String taiYuan;
    /**
     * 胎息
     */
    private String taiXi;
    /**
     * 命宫
     */
    private String mingGong;
    /**
     * 身宫
     */
    private String shenGong;

    /**
     * 命
     */
    private String ming;
    /**
     * 命卦
     */
    private String mingGua;
    /**
     * 命卦基本分析
     */
    private String mingGuaJiBen;
    /**
     * 命卦风水分析
     */
    private String mingGuaFengShui;

    /**
     * 日主属性
     */
    private String dayZhuAttribute;

    /**
     * 同党数量
     */
    private int tongDangCount;
    /**
     * 异党数量
     */
    private int yiDangCount;

    /**
     * 五行木数量（不包含地支藏干）
     */
    private int muCount;
    /**
     * 五行火数量（不包含地支藏干）
     */
    private int huoCount;
    /**
     * 五行土数量（不包含地支藏干）
     */
    private int tuCount;
    /**
     * 五行金数量（不包含地支藏干）
     */
    private int jinCount;
    /**
     * 五行水数量（不包含地支藏干）
     */
    private int shuiCount;

    /**
     * 五行木数量（包含地支藏干）
     */
    private int muZhiCount;
    /**
     * 五行火数量（包含地支藏干）
     */
    private int huoZhiCount;
    /**
     * 五行土数量（包含地支藏干）
     */
    private int tuZhiCount;
    /**
     * 五行金数量（包含地支藏干）
     */
    private int jinZhiCount;
    /**
     * 五行水数量（包含地支藏干）
     */
    private int shuiZhiCount;

    /**
     * 五行缺失（如：五行齐全）
     */
    private List<String> baZiWuXingQueShi;
    /**
     * 五行数量（如：2木 1火 2土 2金 1水）
     */
    private List<String> baZiWuXingCount;
    /**
     * 五行旺衰（如：火旺 土相 木休 水囚 金死）
     */
    private List<String> wuXingWangShuai;

    /**
     * 身体强弱（如：强）
     */
    private String bodyIntensity;
    /**
     * 喜用神（如：木）
     */
    private List<String> xiYongShen;
    /**
     * 喜用神方位（如：北）
     */
    private List<String> xiYongShenFangWei;

    /**
     * 骨重
     */
    private String guZhong;
    /**
     * 骨重批注
     */
    private String guZhongPiZhu;

    /**
     * 日柱论命
     */
    private String dayZhuLunMing;

    /**
     * 姻缘
     */
    private String yinYuan;

    /**
     * 五行分析
     */
    private String wuXingFenXi;

    /**
     * 运势分析
     */
    private String yunShiFenXi;

    /**
     * 性格分析 - 先天性格
     */
    private String xianTianXingGeFenXi;
    /**
     * 性格分析 - 潜在性格
     */
    private String qianZaiXingGeFenXi;
    /**
     * 性格分析 - 外显性格
     */
    private String waiXianXingGeFenXi;

    /**
     * 彭祖百忌
     */
    private String pengZuBaiJi;

    /**
     * 年太岁
     */
    private String yearTaiSui;
    /**
     * 月太岁
     */
    private String monthTaiSui;
    /**
     * 日太岁
     */
    private String dayTaiSui;

    /**
     * 日喜神
     */
    private String dayXiShen;
    /**
     * 日福神
     */
    private String dayFuShen;
    /**
     * 日财神
     */
    private String dayCaiShen;
    /**
     * 日阳贵神
     */
    private String dayYangGuiShen;
    /**
     * 日阴贵神
     */
    private String dayYinGuiShen;

    /**
     * 时喜神
     */
    private String hourXiShen;
    /**
     * 时福神
     */
    private String hourFuShen;
    /**
     * 时财神
     */
    private String hourCaiShen;
    /**
     * 时阳贵神
     */
    private String hourYangGuiShen;
    /**
     * 时阴贵神
     */
    private String hourYinGuiShen;

    /**
     * 值日天神
     */
    private String zhiDayTianShen;
    /**
     * 值时天神
     */
    private String zhiHourTianShen;

    /**
     * 逐月胎神
     */
    private String zhuMonthTaiShen;
    /**
     * 逐日胎神
     */
    private String zhuDayTaiShen;

    /**
     * 日宜
     */
    private List<String> dayYi;
    /**
     * 日忌
     */
    private List<String> dayJi;
    /**
     * 日吉神
     */
    private List<String> dayJiShen;
    /**
     * 日凶煞
     */
    private List<String> dayXiongSha;
    /**
     * 日煞方位
     */
    private String dayShaFangWei;
    /**
     * 日冲
     */
    private String dayChong;

    /**
     * 时宜
     */
    private List<String> hourYi;
    /**
     * 时忌
     */
    private List<String> hourJi;
    /**
     * 时煞方位
     */
    private String hourShaFangWei;
    /**
     * 时冲
     */
    private String hourChong;

    /**
     * 值年九星
     */
    private String zhiYearJiuXing;
    /**
     * 值月九星
     */
    private String zhiMonthJiuXing;
    /**
     * 值日九星
     */
    private String zhiDayJiuXing;
    /**
     * 值时九星
     */
    private String zhiHourJiuXing;

    /**
     * 大运
     */
    private List<List<String>> daYun;
    /**
     * 流年
     */
    private List<List<String>> liuNian;

    /**
     * 大运十神
     */
    private List<List<String>> daYunShiShen;
    /**
     * 流年十神
     */
    private List<List<String>> liuNianShiShen;

    private BaZiShenShaUtil baZiShenShaUtil; // 八字-神煞工具

//****************************************************************************************************************************************************

    /**
     * 使用自定义设置初始化
     *
     * @param setting 八字-设置
     */
    public BaZi(BaZiSetting setting) {
        core(setting);
    }

//====================================================================================================================================================

    /**
     * 获取并设置数据（★核心）
     *
     * @param setting 八字-设置
     */
    private void core(BaZiSetting setting) {

        // 初始化自定义数据
        initialize(setting);

        // 计算数据
        zodiac(setting); // 计算生肖、星座、星期、季节
        baZi(); // 计算八字
        baZiWuXing(); // 计算八字五行
        baZiNaYin(); // 计算八字纳音
        baZiKngWang(); // 计算八字空亡
        qiYun(setting); // 计算起运
        wuXingQueShi(); // 计字五行缺失
        wuXingCount2(); // 计算五行数量（简要）
        taiGong(); // 计算胎元、胎息、命宫、身宫
        zhuXing(); // 计算主星
        diZhiCangGan(); // 计算地支藏干
        fuXing(); // 计算副星
        diShi(); // 计算地势

        if (!setting.getIsShiLi()) {
            shenSha(setting); // 计算常用神煞
            tianGanLiuYi(setting); // 计算天干留意
            diZhiLiuYi(setting); // 计算地支留意
            yueJiang(); // 计算月相、月将、月将神
            jieQi(); // 计算上一节气及日期、下一节气及日期、出生节气
            renYuan(setting); // 计算人元司令分野
            xingXiu(); // 计算星宿、星宿吉凶、星宿吉凶歌诀
            mingGua(); // 计算命、命卦、命卦分析
            dayZhuAttribute(); // 计算日主属性
            tongYiDang(); // 计算同党、异党
            wuXingCount(); // 计算五行数量（详细）
            wuXingWangShuai(); // 计算五行旺衰
            bodyIntensity(); // 计算身体强弱
            xiYongShen(); // 计算喜用神
            xiYongShenFangWei(); // 计算喜用神方位
            guZhong(); // 计算骨重
            dayZhuLunMing(); // 计算日柱论命
            yinYuan(); // 计算姻缘
            wuXingFenXi(); // 计算五行分析
            yunShiFenXi(); // 计算运势分析
            xingGeFenXi(); // 计算性格分析
            pengZuBaiJi(); // 计算彭祖百忌
            taiSui(setting); // 计算计算年太岁、月太岁、日太岁
            shen(); // 计算值日神（日喜神、日福神、日财神、日阳贵神、日阴贵神），值时神（时喜神、时福神、时财神、时阳贵神、时阴贵神）
            zhiTianShen(); // 计算值日天神、值时天神
            zhuTaiShen(); // 计算逐月胎神、逐日胎神
            yiJi(setting); // 计算日宜忌（日宜、日忌、日吉神、日凶煞、日煞方位、日冲），时宜忌（时宜、时忌、时煞方位、时冲）
            jiuXing(setting); // 计算值年九星、值月九星、值日九星、值时九星
            DaYun[] daYun = daYun(setting); // 计算大运及大运十神
            liuNian(daYun); // 计算流年及流年十神
        }

    }

    /**
     * 初始化自定义数据
     *
     * @param setting 八字-设置
     */
    private void initialize(BaZiSetting setting) {

        // 1、设置基础信息
        this.name = setting.getName();
        this.sex = setting.getSex() == 0 ? "女" : "男";
        this.zao = "男".equals(getSex()) ? "乾造" : "坤造";
        this.occupy = setting.getOccupy();
        this.address = setting.getAddress();

        // 2.1、判断日期类型并返回公历日期、农历日期
        Map<String, Object> dateMap = BaZiUtil.isDateType(setting);
        // 2.2、设置日期数据
        this.solar = (Solar) dateMap.get("solar"); // 设置公历日期
        this.lunar = (Lunar) dateMap.get("lunar"); // 设置农历日期
        Date date;
        Calendar c = Calendar.getInstance();
        c.set(getSolar().getYear(), getSolar().getMonth() - 1, getSolar().getDay(), getSolar().getHour(), 0, 0);
        date = c.getTime();
        this.date = date;

        // 3.1、判断干支设置并返回干支
        Map<String, List<String>> ganZhiMap = BaZiUtil.isGanZhi(setting, getSolar().getLunar());
        // 3.2、设置年干支
        List<String> yearGanZhi = ganZhiMap.get("yearGanZhi");
        this.yearGan = yearGanZhi.get(0); // 年干
        this.yearZhi = yearGanZhi.get(1); // 年支
        this.yearGanZhi = yearGanZhi.get(2); // 年干支
        // 3.3、设置月干支
        List<String> monthGanZhi = ganZhiMap.get("monthGanZhi");
        this.monthGan = monthGanZhi.get(0); // 月干
        this.monthZhi = monthGanZhi.get(1); // 月支
        this.monthGanZhi = monthGanZhi.get(2); // 月干支
        // 3.4、设置日干支
        List<String> dayGanZhi = ganZhiMap.get("dayGanZhi");
        this.dayGan = dayGanZhi.get(0); // 日干
        this.dayZhi = dayGanZhi.get(1); // 日支
        this.dayGanZhi = dayGanZhi.get(2); // 日干支
        // 3.5、设置时干支
        List<String> hourGanZhi = ganZhiMap.get("hourGanZhi");
        this.hourGan = hourGanZhi.get(0); // 时干
        this.hourZhi = hourGanZhi.get(1); // 时支
        this.hourGanZhi = hourGanZhi.get(2); // 时干支

    }

    /**
     * 计算生肖、星座、星期、季节
     *
     * @param setting 八字-设置
     */
    private void zodiac(BaZiSetting setting) {

        // 1、计算生肖
        if (setting.getYearGanZhiSet() == 0) {
            this.zodiac = getLunar().getYearShengXiao(); // 以正月初一起算
        } else if (setting.getYearGanZhiSet() == 1) {
            this.zodiac = getLunar().getYearShengXiaoByLiChun(); // 以立春当天起算
        } else if (setting.getYearGanZhiSet() == 2) {
            this.zodiac = getLunar().getYearShengXiaoExact(); // 以立春交接时刻起算
        }

        // 2、计算星座
        this.constellation = getSolar().getXingZuo() + "座";

        // 3、计算星期
        this.week = "周" + getLunar().getWeekInChinese();

        // 4、计算季节
        this.season = getLunar().getSeason().substring(1, 2); // 季节简称（如：春）

    }

    /**
     * 计算八字
     */
    private void baZi() {

        this.baZi = Arrays.asList(getYearGanZhi(), getMonthGanZhi(), getDayGanZhi(), getHourGanZhi());

    }

    /**
     * 计算八字五行
     */
    private void baZiWuXing() {

        Map<String, String> ganMap = BaZiMap.GAN_WU_XING; // 天干五行（天干为键）
        Map<String, String> zhiMap = BaZiMap.ZHI_WU_XING; // 地支五行（地支为键）

        this.yearGanWuXing = ganMap.get(getYearGan());   // 年干五行
        this.monthGanWuXing = ganMap.get(getMonthGan()); // 月干五行
        this.dayGanWuXing = ganMap.get(getDayGan());     // 日干五行
        this.hourGanWuXing = ganMap.get(getHourGan());   // 时干五行

        this.yearZhiWuXing = zhiMap.get(getYearZhi());   // 年支五行
        this.monthZhiWuXing = zhiMap.get(getMonthZhi()); // 月支五行
        this.dayZhiWuXing = zhiMap.get(getDayZhi());     // 日支五行
        this.hourZhiWuXing = zhiMap.get(getHourZhi());   // 时支五行

        this.yearGanZhiWuXing = getYearGanWuXing() + getYearZhiWuXing();    // 年干支五行
        this.monthGanZhiWuXing = getMonthGanWuXing() + getMonthZhiWuXing(); // 月干支五行
        this.dayGanZhiWuXing = getDayGanWuXing() + getDayZhiWuXing();       // 日干支五行
        this.hourGanZhiWuXing = getHourGanWuXing() + getHourZhiWuXing();    // 时干支五行

        this.baZiWuXing = Arrays.asList(getYearGanZhiWuXing(), getMonthGanZhiWuXing(), getDayGanZhiWuXing(), getHourGanZhiWuXing());

    }

    /**
     * 计算八字纳音
     */
    private void baZiNaYin() {

        Map<String, String> naYin = BaZiMap.NA_YIN; // 纳音（干支为键）

        this.yearGanZhiNaYin = naYin.get(getYearGanZhi());   // 年干支纳音
        this.monthGanZhiNaYin = naYin.get(getMonthGanZhi()); // 月干支纳音
        this.dayGanZhiNaYin = naYin.get(getDayGanZhi());     // 日干支纳音
        this.hourGanZhiNaYin = naYin.get(getHourGanZhi());   // 时干支纳音

        this.baZiNaYin = Arrays.asList(getYearGanZhiNaYin(), getMonthGanZhiNaYin(), getDayGanZhiNaYin(), getHourGanZhiNaYin());

    }

    /**
     * 计算八字空亡
     */
    private void baZiKngWang() {

        Map<String, String> kongWang = BaZiMap.KONG_WANG; // 空亡（干支为键）

        this.yearGanZhiKongWang = kongWang.get(getYearGanZhi()); // 年干支空亡
        this.monthGanZhiKongWang = kongWang.get(getMonthGanZhi()); // 月干支空亡
        this.dayGanZhiKongWang = kongWang.get(getDayGanZhi()); // 日干支空亡
        this.hourGanZhiKongWang = kongWang.get(getHourGanZhi()); // 时干支空亡

        this.baZiKongWang = Arrays.asList(getYearGanZhiKongWang(), getMonthGanZhiKongWang(), getDayGanZhiKongWang(), getHourGanZhiKongWang());

    }

    /**
     * 计算起运
     *
     * @param setting 八字-设置
     */
    private void qiYun(BaZiSetting setting) {

        EightChar ec = getLunar().getEightChar();
        ec.setSect(setting.getDayGanZhiSet()); // 日干支设置，同子时流派（0:晚子时日柱按明天。1:晚子时日柱按当天）

        // 初始化运（设置性别、起运流派）
        Yun yun = ec.getYun(setting.getSex(), setting.getQiYunLiuPai() + 1);

        String qiYun = "出生";
        if (yun.getStartYear() != 0) qiYun += yun.getStartYear() + "年";
        if (yun.getStartMonth() != 0) qiYun += yun.getStartMonth() + "个月";
        if (yun.getStartDay() != 0) qiYun += yun.getStartDay() + "天";
        if (yun.getStartHour() != 0) qiYun += yun.getStartHour() + "分钟";
        qiYun += "后开始起运";

        this.qiYun = qiYun;
        this.qiYunDate = yun.getStartSolar().toYmdHms();

    }

    /**
     * 计算五行缺失
     */
    private void wuXingQueShi() {

        Map<String, String> ganWuXing = BaZiMap.GAN_WU_XING; // 天干五行
        Map<String, String> zhiWuXing = BaZiMap.ZHI_WU_XING; // 地支五行

        // 1、添加八字五行数据
        Set<String> set = new HashSet<>(Arrays.asList(
                ganWuXing.get(getYearGan()), ganWuXing.get(getMonthGan()), ganWuXing.get(getDayGan()), ganWuXing.get(getHourGan()),
                zhiWuXing.get(getYearZhi()), zhiWuXing.get(getMonthZhi()), zhiWuXing.get(getDayZhi()), zhiWuXing.get(getHourZhi())
        ));
        List<String> list = new ArrayList<>(set); // set转list

        // 2、判断五行是否缺失
        List<String> baZiWuXingQueShi = new ArrayList<>();
        if (list.size() == 5) {
            baZiWuXingQueShi.add("五行齐全");
            this.baZiWuXingQueShi = baZiWuXingQueShi;
            return;
        }

        // 3.1、初始化五行
        List<String> wuXingList = Arrays.asList("木", "火", "土", "金", "水");
        // 3.2、获取并设置缺失的五行
        baZiWuXingQueShi = CommonUtil.getListUnlike(list, wuXingList);
        this.baZiWuXingQueShi = baZiWuXingQueShi;

    }

    /**
     * 计算五行数量（简要）
     */
    private void wuXingCount2() {

        // 1.1、添加干支五行
        List<String> ganZHiWuXingList = Arrays.asList(
                getYearGanWuXing(), getMonthGanWuXing(), getDayGanWuXing(), getHourGanWuXing(),
                getYearZhiWuXing(), getMonthZhiWuXing(), getDayZhiWuXing(), getHourZhiWuXing()
        );
        // 1.2、获取八字五行中出现的重复元素及出现次数
        Map<String, Integer> map = CommonUtil.getListIdentical(ganZHiWuXingList);

        // 2、保存五行数量
        List<String> baZiWuXingCount = new ArrayList<>();
        for (String key : map.keySet()) {
            baZiWuXingCount.add(map.get(key) + key);
        }

        this.baZiWuXingCount = baZiWuXingCount;

    }

    /**
     * 计算胎元、胎息、命宫、身宫
     */
    private void taiGong() {

        EightChar ec = getLunar().getEightChar();

        this.taiYuan = ec.getTaiYuan() + "（" + ec.getTaiYuanNaYin() + "）"; // 胎元
        this.taiXi = ec.getTaiXi() + "（" + ec.getTaiXiNaYin() + "）"; // 胎息
        this.mingGong = ec.getMingGong() + "（" + ec.getMingGongNaYin() + "）"; // 命宫
        this.shenGong = ec.getShenGong() + "（" + ec.getShenGongNaYin() + "）"; // 身宫

    }

    /**
     * 计算主星
     */
    private void zhuXing() {

        /*
            ★计算方法：根据日干与年干、月干、时干的生克关系得出

            ========================================================================================

                                               十神生克关系

                1、生我者为印缓（五行阴阳属性相同则为：偏印，五行阴阳属性不同则为：正印）
                2、我生者为子孙（五行阴阳属性相同则为：食神，五行阴阳属性不同则为：伤官）
                3、克我者为官鬼（五行阴阳属性相同则为：七杀，五行阴阳属性不同则为：正官）
                4、我克者为妻财（五行阴阳属性相同则为：偏财，五行阴阳属性不同则为：正财）
                5、同我者为兄弟（五行阴阳属性相同则为：比肩，五行阴阳属性不同则为：劫财）
         */

        Map<String, String> shiShen = BaZiMap.SHI_SHEN_MING_PAN_MAP; // 十神，用于命盘（日干+其他干支为键）

        this.yearGanZhiZhuXing = shiShen.get(getDayGan() + getYearGan()); // 年干支主星
        this.monthGanZhiZhuXing = shiShen.get(getDayGan() + getMonthGan()); // 月干支主星
        this.dayGanZhiZhuXing = "元" + getSex(); // 日干支主星
        this.hourGanZhiZhuXing = shiShen.get(getDayGan() + getHourGan()); // 时干支主星

    }

    /**
     * 计算地支藏干
     */
    private void diZhiCangGan() {

        /*
                 《十二地支藏干口诀》

            子宫壬癸在其中，丑癸辛金己土同；
            寅宫甲木兼丙戊，卯宫甲乙木相逢，
            辰藏乙戊三分癸，已中庚金丙戊丛；
            午宫丙丁火己土，未宫乙己丁共宗；
            申位庚金壬水戊，酉宫庚辛金丰隆；
            戌宫辛金及丁戊，亥藏壬甲戊真踪。

            =========================================================================

            ★解释：
                1、 子：藏干为癸水。
                2、 丑：藏干为已土、癸水、辛金。（已土为本气，癸水为中气，辛金为余气）
                3、 寅：藏干为甲木、丙火、戊土。（甲木为本气，丙火为中气，戊土为余气）
                4、 卯：藏干为乙木。
                5、 辰：藏干为戊土、乙木、癸水。（戊土为本气，乙木为中气，癸水为余气）
                6、 已：藏干为丙火、庚金、戊土。（丙火为本气，庚金为中气，戊土为余气）
                7、 午：藏干为丁火、已土。（丁火为本气，已土为中气）
                8、 未：藏干为已土、丁火、乙木。（已土为本气，丁火为中气，乙木为余气）
                9、 申：藏干为庚金、壬水、戊土。（庚金为本气，壬水为中气，戊土为余气）
                10、酉：藏干为辛金。
                11、戌：藏干为戊土、辛金、丁火。（戊土为本气，辛金为中气，丁火为余气）
                12、亥：藏干为壬水、甲木。（壬水为本气，甲木为中气）
        */

        Map<String, List<String>> diZhiCangGan = BaZiMap.DI_ZHI_CANG_GAN; // 地支藏干（地支为键）

        this.yearZhiCangGan = diZhiCangGan.get(getYearZhi());   // 年支藏干
        this.monthZhiCangGan = diZhiCangGan.get(getMonthZhi()); // 月支藏干
        this.dayZhiCangGan = diZhiCangGan.get(getDayZhi());     // 日支藏干
        this.hourZhiCangGan = diZhiCangGan.get(getHourZhi());   // 时支藏干

    }

    /**
     * 计算副星
     */
    private void fuXing() {

        /*
            ★根据日干与年支藏干、月支藏干、日支藏干、时支藏干得出

            ===========================================================================

            十神的生克关系：
                1、生我者为印缓（五行阴阳属性相同则为：偏印，五行阴阳属性不同则为：正印）
                2、我生者为子孙（五行阴阳属性相同则为：食神，五行阴阳属性不同则为：伤官）
                3、克我者为官鬼（五行阴阳属性相同则为：七杀，五行阴阳属性不同则为：正官）
                4、我克者为妻财（五行阴阳属性相同则为：偏财，五行阴阳属性不同则为：正财）
                5、同我者为兄弟（五行阴阳属性相同则为：比肩，五行阴阳属性不同则为：劫财）
         */

        Map<String, String> shiShen = BaZiMap.SHI_SHEN_MING_PAN_MAP; // 十神，用于命盘（日干+其他干支为键）

        List<String> yearGanZhiFuXing = new ArrayList<>();
        List<String> monthGanZhiFuXing = new ArrayList<>();
        List<String> dayGanZhiFuXing = new ArrayList<>();
        List<String> hourGanZhiFuXing = new ArrayList<>();
        for (String cangGan : getYearZhiCangGan()) {
            yearGanZhiFuXing.add(shiShen.get(getDayGan() + cangGan)); // 年干支副星
        }
        for (String cangGan : getMonthZhiCangGan()) {
            monthGanZhiFuXing.add(shiShen.get(getDayGan() + cangGan)); // 月干支副星
        }
        for (String cangGan : getDayZhiCangGan()) {
            dayGanZhiFuXing.add(shiShen.get(getDayGan() + cangGan)); // 日干支副星
        }
        for (String cangGan : getHourZhiCangGan()) {
            hourGanZhiFuXing.add(shiShen.get(getDayGan() + cangGan)); // 时干支副星
        }

        this.yearGanZhiFuXing = yearGanZhiFuXing; // 年干支副星
        this.monthGanZhiFuXing = monthGanZhiFuXing; // 月干支副星
        this.dayGanZhiFuXing = dayGanZhiFuXing; // 日干支副星
        this.hourGanZhiFuXing = hourGanZhiFuXing; // 时干支副星

    }

    /**
     * 计算地势
     */
    private void diShi() {

        Map<String, String> shiErZhangSheng = BaZiMap.SHI_ER_ZHANG_SHENG; // 十二长生（日干+地支为键）

        this.yearGanZhiDiShi = shiErZhangSheng.get(getDayGan() + getYearZhi()); // 年干支地势
        this.monthGanZhiDiShi = shiErZhangSheng.get(getDayGan() + getMonthZhi()); // 月干支地势
        this.dayGanZhiDiShi = shiErZhangSheng.get(getDayGan() + getDayZhi()); // 日干支地势
        this.hourGanZhiDiShi = shiErZhangSheng.get(getDayGan() + getHourZhi()); // 时干支地势

    }

    /**
     * 计算常用神煞
     *
     * @param setting 八字-设置
     */
    private void shenSha(BaZiSetting setting) {

        int sex = "女".equals(getSex()) ? 0 : 1; // 性别
        String yearGanZhiNaYinWuXing = getYearGanZhiNaYin().substring(2, 3); // 年干支纳音五行

        this.baZiShenShaUtil = new BaZiShenShaUtil(setting, getBaZi(), yearGanZhiNaYinWuXing, getSeason(), null);
        this.yearGanZhiShenSha = getBaZiShenShaUtil().getYearGanZhiShenSha();   // 年干支神煞
        this.monthGanZhiShenSha = getBaZiShenShaUtil().getMonthGanZhiShenSha(); // 月干支神煞
        this.dayGanZhiShenSha = getBaZiShenShaUtil().getDayGanZhiShenSha();     // 日干支神煞
        this.hourGanZhiShenSha = getBaZiShenShaUtil().getHourGanZhiShenSha();   // 时干支神煞

    }

    /**
     * 计算天干留意
     *
     * @param setting 八字-设置
     */
    private void tianGanLiuYi(BaZiSetting setting) {

        Map<String, String> xiangSheng = BaZiMap.TIAN_GAN_XIANG_SHENG; // 天干相生（天干+天干为键）
        Map<String, String> xiangHe = BaZiMap.TIAN_GAN_XIANG_HE; // 天干相合（天干+天干为键）
        Map<String, String> xiangChong = BaZiMap.TIAN_GAN_XIANG_CHONG; // 天干相冲（天干+天干为键）
        Map<String, String> xiangKe = BaZiMap.TIAN_GAN_XIANG_KE; // 天干相克（天干+天干为键）

        Set<String> set = new HashSet<>();

        if (setting.getTianGanXiangShengSet()) saveTianGanLiuYi(set, xiangSheng); // 天干相生
        if (setting.getTianGanXiangHeSet()) saveTianGanLiuYi(set, xiangHe); // 天干相合
        if (setting.getTianGanXiangChongSet()) saveTianGanLiuYi(set, xiangChong); // 天干相冲
        if (setting.getTianGanXiangKeSet()) saveTianGanLiuYi(set, xiangKe); // 天干相克

        set.removeIf(Objects::isNull); // 删除所有null
        this.tianGanLiuYi = new ArrayList<>(set);

    }

    /**
     * 计算地支留意
     *
     * @param setting 八字-设置
     */
    private void diZhiLiuYi(BaZiSetting setting) {

        Map<String, String> banHe = BaZiMap.DI_ZHI_BAN_HE; // 地支半合（地支+地支为键）
        Map<String, String> gongHe = BaZiMap.DI_ZHI_GONG_HE; // 地支拱合（地支+地支为键）
        Map<String, String> anHe = BaZiMap.DI_ZHI_AN_HE; // 地支暗合（地支+地支为键）
        Map<String, String> sanHe = BaZiMap.DI_ZHI_SAN_HE; // 地支三合（地支+地支+地支为键）
        Map<String, String> liuHe = BaZiMap.DI_ZHI_LIU_HE; // 地支六合（地支+地支为键）
        Map<String, String> xiangXing = BaZiMap.DI_ZHI_XIANG_XING; // 地支相刑（地支+地支为键）
        Map<String, String> sanXing = BaZiMap.DI_ZHI_SAN_XING; // 地支三刑（地支+地支+地支为键）
        Map<String, String> xiangChong = BaZiMap.DI_ZHI_XIANG_CHONG; // 地支相冲（地支+地支为键）
        Map<String, String> xiangPo = BaZiMap.DI_ZHI_XIANG_PO; // 地支相破（地支+地支为键）
        Map<String, String> xiangHai = BaZiMap.DI_ZHI_XIANG_HAI; // 地支相害（地支+地支为键）

        Set<String> set = new HashSet<>();

        if (setting.getDiZhiBanHeSet()) saveDiZhiLiuYi(set, banHe); // 地支半合
        if (setting.getDiZhiGongHeSet()) saveDiZhiLiuYi(set, gongHe); // 地支拱合
        if (setting.getDiZhiAnHeSet()) saveDiZhiLiuYi(set, anHe); // 地支暗合
        if (setting.getDiZhiSanHeSet()) saveDiZhiLiuYi2(set, sanHe); // 地支三合
        if (setting.getDiZhiLiuHeSet()) saveDiZhiLiuYi(set, liuHe); // 地支六合
        if (setting.getDiZhiXiangXingSet()) saveDiZhiLiuYi(set, xiangXing); // 地支相刑
        if (setting.getDiZhiSanXingSet()) saveDiZhiLiuYi2(set, sanXing); // 地支三刑
        if (setting.getDiZhiXiangChongSet()) saveDiZhiLiuYi(set, xiangChong); // 地支相冲
        if (setting.getDiZhiXiangPoSet()) saveDiZhiLiuYi(set, xiangPo); // 地支相破
        if (setting.getDiZhiXiangHaiSet()) saveDiZhiLiuYi(set, xiangHai); // 地支相害

        set.removeIf(Objects::isNull); // 删除所有null
        this.diZhiLiuYi = new ArrayList<>(set);

    }

    /**
     * 计算月相、月将、月将神
     */
    private void yueJiang() {

        String monthZhi = getMonthZhi(); // 月支
        this.yueXiang = getLunar().getYueXiang(); // 月相
        this.yueJiang = BaZiMap.YUE_JIANG.get(monthZhi).get(0); // 月将
        this.yueJiangShen = BaZiMap.YUE_JIANG.get(monthZhi).get(1); // 月将神

    }

    /**
     * 计算上一节气及日期、下一节气及日期、出生节气
     */
    private void jieQi() {

        Solar solar = getSolar(); // 公历日期
        Lunar lunar = getLunar(); // 农历日期

        // 1、计算上一节气、上一节气日期
        JieQi prevJieQi = lunar.getPrevJie(true);
        this.prevJieQi = prevJieQi.toString(); // 上一节气
        String prevSolar = prevJieQi.getSolar().toYmdHms();
        this.prevJieQiDate = prevSolar; // 上一节气日期

        // 2、计算下一节气、下一节气日期
        JieQi nextJieQi = lunar.getNextJie(true);
        this.nextJieQi = nextJieQi.toString(); // 下一节气
        String nextSolar = nextJieQi.getSolar().toYmdHms();
        this.nextJieQiDate = nextSolar; // 下一节气日期

        // 3、计算上一节气与所选日期的时间间隔
        Map<String, Long> prevMap = DateUtil.dateInterval(prevSolar, solar.toYmdHms());

        // 4、计算所选日期与下一节气的时间间隔
        Map<String, Long> nextMap = DateUtil.dateInterval(solar.toYmdHms(), nextSolar);

        // 5、设置数据
        this.prevJieQiDayNumber = Math.toIntExact(prevMap.get("days")); // 所选日期距上一节气天数
        this.nextJieQiDayNumber = Math.toIntExact(nextMap.get("days")); // 所选日期距下一节气天数
        String prevStr = "出生于" + prevJieQi + "后" + prevMap.get("days") + "天" + prevMap.get("hours") + "小时" + prevMap.get("minutes") + "分" + prevMap.get("seconds") + "秒";
        String nexStr = nextJieQi + "前" + nextMap.get("days") + "天" + nextMap.get("hours") + "小时" + nextMap.get("minutes") + "分" + nextMap.get("seconds") + "秒";
//        String prevStr = "出生于" + prevJieQi + "后" + prevMap.get("days") + "天" + prevMap.get("hours") + "小时";
//        String nexStr = nextJieQi + "前" + nextMap.get("days") + "天" + nextMap.get("hours") + "小时";
        this.birthSolarTerms = prevStr + "，" + nexStr;

    }

    /**
     * 计算人元司令分野
     *
     * @param setting 八字-设置
     */
    private void renYuan(BaZiSetting setting) {

        String renYuan = "";

        int prevJieDayNumber = (getPrevJieQiDayNumber() < 0 || getPrevJieQiDayNumber() > 29) ? 1 : getPrevJieQiDayNumber();

        // 1、判断计算方式
        if (setting.getRenYuanType() == 0) {
            // 1.1、子平真诠法决
            Map<String, List<String>> ziRenYuan = BaZiMap.ZI_REN_YUAN;
            renYuan = ziRenYuan.get(getMonthZhi()).get(prevJieDayNumber);
        } else if (setting.getRenYuanType() == 1) {
            // 1.2、渊海子平法决
            Map<String, List<String>> yuanRenYuan = BaZiMap.YUAN_REN_YUAN;
            renYuan = yuanRenYuan.get(getMonthZhi()).get(prevJieDayNumber);
        } else if (setting.getRenYuanType() == 2) {
            // 1.3、星平会海法决
            Map<String, List<String>> xingRenYuan = BaZiMap.XING_REN_YUAN;
            renYuan = xingRenYuan.get(getMonthZhi()).get(prevJieDayNumber);
        } else if (setting.getRenYuanType() == 3) {
            // 1.4、三命通会法决
            Map<String, List<String>> xingRenYuan = BaZiMap.SAN_REN_YUAN;
            renYuan = xingRenYuan.get(getMonthZhi()).get(prevJieDayNumber);
        } else if (setting.getRenYuanType() == 4) {
            // 1.5、神峰通考法决
            Map<String, List<String>> xingRenYuan = BaZiMap.SHEN_REN_YUAN;
            renYuan = xingRenYuan.get(getMonthZhi()).get(prevJieDayNumber);
        } else if (setting.getRenYuanType() == 5) {
            // 1.6、万育吾之法决
            Map<String, List<String>> xingRenYuan = BaZiMap.WAN_REN_YUAN;
            renYuan = xingRenYuan.get(getMonthZhi()).get(prevJieDayNumber);
        }

        // 2、处理数据
        Map<String, String> ganYinYangWuXing = BaZiMap.GAN_WU_XING; // 天干五行
        if (!"".equals(renYuan)) {
            String wuXing = ganYinYangWuXing.get(renYuan); // 获取人元五行
            this.renYuan = renYuan + wuXing + "值令";
        }

    }

    /**
     * 计算星宿、星宿吉凶、星宿吉凶歌诀
     */
    private void xingXiu() {

        this.xingXiu = getLunar().getXiu() + "宿" + getLunar().getGong() + "方" + getLunar().getShou(); // 星宿
        this.xiuJiXiong = getLunar().getXiuLuck(); // 星宿吉凶
        this.xiuJiXiongGeJue = getLunar().getXiuSong(); // 星宿吉凶歌诀

    }

    /**
     * 计算命、命卦、命卦分析
     */
    private void mingGua() {

        /*
            一、男命：
                1、年份中的每一个数字（例如：2000年→ 2+0+0+0=2）。
                2、相加得到数字A（例如：2）。
                3、用得到数字A的每一个数字相加再得到数字B（例如：2）。
                4、若数字B小于10，则使用(11-数字B);若数字B大于10，则使用(数字B-11)。

            二、女命：
                1、年份中的每一个数字（例如：2000年→ 2+0+0+0=2）。
                2、相加得到一个数字A（例如：2）。
                3、用数字A+4得到数字B（例如：2+4=6）。
                4、若数字B大于9，再用数字B-9；如没有余数或除尽则视为9。
         */

        // 1、计算命
        this.ming = getYearGanZhiNaYin() + "命";

        // 2、计算年份合数
        int yearCount = 0; // 年份合数
        String yearStr = String.valueOf(getLunar().getYear());
        for (int i = 0; i < yearStr.length(); i++) {
            yearCount += Integer.parseInt(yearStr.split("")[i]);
        }

        Map<Integer, String> mingGua = BaZiMap.MING_GUA; // 命卦（命卦宫位为键）
        Map<String, List<String>> mingGuaFenXi = BaZiMap.MING_GUA_FEN_XI; // 命卦分析（命卦为键）

        // 3、男命
        if ("男".equals(getSex())) {
            // 3.1、若年份合数大于10，则继续使用年份合数相加，直至小于10为止
            while (true) {
                if (yearCount > 10) {
                    String yearCountStr = String.valueOf(yearCount);
                    yearCount = 0;
                    for (int i = 0; i < yearCountStr.length(); i++) {
                        yearCount += Integer.parseInt(yearCountStr.split("")[i]);
                    }
                } else break;
            }
            // 3.2、使用（11-数字之和）得出男命命卦宫位
            yearCount = 11 - yearCount == 5 ? 2 : 11 - yearCount; // 男命命卦宫位为5时，寄坤宫
            this.mingGua = mingGua.get(yearCount); // 获取命卦
            this.mingGuaJiBen = mingGuaFenXi.get(getMingGua()).get(0); // 获取命卦基本分析
            this.mingGuaFengShui = mingGuaFenXi.get(getMingGua()).get(1); // 获取命卦基本分析
        } else {
            // 4、女命
            int womManMingGuaGong = yearCount + 4; // 数字B
            // 4.1、若数字B大于9，再用数字B-9；如没有余数或除尽则视为9
            while (true) {
                if (womManMingGuaGong > 9) {
                    womManMingGuaGong -= 9;
                } else break;
            }
            // 4.2、得出女命命卦宫位，并获取命卦
            womManMingGuaGong = womManMingGuaGong == 5 ? 8 : womManMingGuaGong; // 女命命卦宫位为5时，寄艮宫
            this.mingGua = mingGua.get(womManMingGuaGong); // 获取命卦
            this.mingGuaJiBen = mingGuaFenXi.get(getMingGua()).get(0); // 获取命卦基本分析
            this.mingGuaFengShui = mingGuaFenXi.get(getMingGua()).get(1); // 获取命卦基本分析
        }

    }

    /**
     * 计算日主属性
     */
    private void dayZhuAttribute() {

        this.dayZhuAttribute = getDayGan() + getDayGanWuXing();

    }

    /**
     * 计算同党、异党
     */
    private void tongYiDang() {

        /*
            查法：以日干（我）查其余干支（者）

                1、五行生我者、同我者的干支，为日主同党。
                2、五行我生者、我克者、克我者的干支，为日主异党。
         */

        Map<String, String> ganWuXing = BaZiMap.GAN_WU_XING; // 天干五行
        Map<String, String> wuXingTongYi = BaZiMap.WU_XING_TONG_YI; // 以日干五行和其余干支五行获取同党或异党

        // 1、计算日干与天干的同党及数量、异党及数量
        addTongYiDang(wuXingTongYi, getDayGanWuXing(), getYearGanWuXing()); // 日干五行+年干五行
        addTongYiDang(wuXingTongYi, getDayGanWuXing(), getMonthGanWuXing()); // 日干五行+月干五行
        addTongYiDang(wuXingTongYi, getDayGanWuXing(), getHourGanWuXing()); // 日干五行+时干五行

        // 2、计算日干与地支的同党及数量、异党及数量
        addTongYiDang(wuXingTongYi, getDayGanWuXing(), getYearZhiWuXing()); // 日干五行+年支五行
        addTongYiDang(wuXingTongYi, getDayGanWuXing(), getMonthZhiWuXing()); // 日干五行+月支五行
        addTongYiDang(wuXingTongYi, getDayGanWuXing(), getDayZhiWuXing()); // 日干五行+日支五行
        addTongYiDang(wuXingTongYi, getDayGanWuXing(), getHourZhiWuXing()); // 日干五行+时支五行

        // 3、计算日干与地支藏干的同党及数量、异党及数量
        for (int i = 0; i < getYearZhiCangGan().size(); i++) {
            String yearGan = getYearZhiCangGan().get(i); // 年支藏干
            addTongYiDang(wuXingTongYi, getDayGanWuXing(), ganWuXing.get(yearGan)); // 日干五行+年支藏干五行
        }
        for (int i = 0; i < getMonthZhiCangGan().size(); i++) {
            String monthGan = getMonthZhiCangGan().get(i); // 月支藏干
            addTongYiDang(wuXingTongYi, getDayGanWuXing(), ganWuXing.get(monthGan)); // 日干五行+月支藏干五行
        }
        for (int i = 0; i < getDayZhiCangGan().size(); i++) {
            String dayGan = getDayZhiCangGan().get(i); // 日支藏干
            addTongYiDang(wuXingTongYi, getDayGanWuXing(), ganWuXing.get(dayGan)); // 日干五行+日支藏干五行
        }
        for (int i = 0; i < getHourZhiCangGan().size(); i++) {
            String hourGan = getHourZhiCangGan().get(i); // 时支藏干
            addTongYiDang(wuXingTongYi, getDayGanWuXing(), ganWuXing.get(hourGan)); // 日干五行+时支藏干五行
        }

    }

    /**
     * 计算五行数量（详细）
     */
    private void wuXingCount() {

        Map<String, String> ganWuXing = BaZiMap.GAN_WU_XING; // 天干五行

        // 1、计算干支五行数量（不包含地支藏干）
        isWuXing(getYearGanWuXing()); // 年干五行
        isWuXing(getYearZhiWuXing()); // 年支五行
        isWuXing(getMonthGanWuXing()); // 月干五行
        isWuXing(getMonthZhiWuXing()); // 月支五行
        isWuXing(getDayGanWuXing()); // 日干五行
        isWuXing(getDayZhiWuXing()); // 日支五行
        isWuXing(getHourGanWuXing()); // 时干五行
        isWuXing(getHourZhiWuXing()); // 时支五行

        // 2、计算地支藏干五行数量（包含地支藏干）
        for (int i = 0; i < getYearZhiCangGan().size(); i++) {
            isZhiWuXing(ganWuXing.get(getYearZhiCangGan().get(i))); // 年支藏干五行
        }
        for (int i = 0; i < getMonthZhiCangGan().size(); i++) {
            isZhiWuXing(ganWuXing.get(getMonthZhiCangGan().get(i))); // 月支藏干五行
        }
//        for (int i = 0; i < getDayZhiCangGan().size(); i++) {
//            isZhiWuXing(map.get(getDayZhiCangGan().get(i))); // 日支藏干五行
//        }
        for (int i = 0; i < getHourZhiCangGan().size(); i++) {
            isZhiWuXing(ganWuXing.get(getHourZhiCangGan().get(i))); // 时支藏干五行
        }

        // 3、设置五行数据
        this.muZhiCount += getMuCount();
        this.huoZhiCount += getHuoCount();
        this.tuZhiCount += getTuCount();
        this.jinZhiCount += getJinCount();
        this.shuiZhiCount += getShuiCount();

    }

    /**
     * 计算五行旺衰
     */
    private void wuXingWangShuai() {

        Map<String, List<String>> wangShuai = BaZiMap.WU_XING_WANG_SHUAI; // 五行旺衰（按月支判断）
        this.wuXingWangShuai = wangShuai.get(getMonthZhi());

    }

    /**
     * 计算身体强弱
     */
    private void bodyIntensity() {

        /*
            1、根据[日元]和[月令]之间的五行生克关系计算。

                解释：日元代表自己，月令代表父母或兄弟。
                口诀：同我、生我为强；克我、我生、我克为弱。
            ----------------------------------------------------

            2、根据[日元]和[其他干支]之间的算分进行计算。

            ----------------------------------------------------
            TODO：此处采用第2种方法：根据[日元]和[其他干支]之间的算分进行计算，暂不考虑其他因素。
         */

        Map<String, String> shengKe = BaZiMap.GAN_ZHI_WU_XING_SHENG_KE; // 天干和干支的五行生克关系

        // 1、根据[日元]和[月令]之间的五行生克关系计算
//        String bodyIntensity = shengKe.get(getDayGan() + getMonthZhi());
//        System.out.println("身体强弱：" + bodyIntensity);

        // 2、根据[日元]和[其他干支]之间的算分进行计算
        int jiaFen = 0; // 加分
        // 2.1、通过日元（日干）与年干的五行生克关系算出加分
        jiaFen += jiaFen(shengKe, getDayGan(), getYearGan(), 8); // 年干统一为8分
        // 2.2、通过日元（日干）与年支的五行生克关系算出加分
        jiaFen += jiaFen(shengKe, getDayGan(), getYearZhi(), 4); // 年支统一为4分
        // 2.3、通过日元（日干）与月干的五行生克关系算出加分
        jiaFen += jiaFen(shengKe, getDayGan(), getMonthGan(), 12); // 月干统一为12分
        // 2.4、通过日元（日干）与月支的五行生克关系算出加分
        jiaFen += jiaFen(shengKe, getDayGan(), getMonthZhi(), 40); // 月支统一为40分
        // 2.5、通过日元（日干）与日支的五行生克关系算出加分
        jiaFen += jiaFen(shengKe, getDayGan(), getDayZhi(), 12); // 日支统一为12分
        // 2.6、通过日元（日干）与时干的五行生克关系算出加分
        jiaFen += jiaFen(shengKe, getDayGan(), getHourGan(), 12); // 时干统一为12分
        // 2.7、通过日元（日干）与时支的五行生克关系算出加分
        jiaFen += jiaFen(shengKe, getDayGan(), getHourZhi(), 12); // 时支统一为12分

        // 3、加分判断
        if (jiaFen == 50) {
            // 3.1、若加分等于50，身体强弱为：平衡（中庸之道）
            this.bodyIntensity = "平衡"; // 平衡（中庸之道）
        } else if (jiaFen >= 40 && jiaFen <= 60) {
            // 3.2、若加分>=40且<=60，身体强弱为：接近平衡（中庸之道）
            this.bodyIntensity = "接近平衡"; // 接近平衡（中庸之道）
        } else if (jiaFen < 40) {
            // 3.3、若加分小于40，身体强弱为：身弱
            this.bodyIntensity = "身弱"; // 身弱
        } else {
            // 3.4、若加分大于60，身体强弱为：身强
            this.bodyIntensity = "身强"; // 身强
        }

    }

    /**
     * 计算喜用神
     */
    private void xiYongShen() {

        /*
            身强的喜用神：克我、我生、我克的干支。
            身弱的喜用神：同我、生我的干支。
        */

        Set<String> set = new HashSet<>();
        Map<String, String> ganWuXing = BaZiMap.GAN_WU_XING; // 天干五行
        Map<String, String> zhiWuXing = BaZiMap.ZHI_WU_XING; // 地支五行
        Map<String, String> shengKe = BaZiMap.GAN_ZHI_WU_XING_SHENG_KE;// 天干和干支的五行生克关系

        // 1、若身强，则寻找：克我、我生、我克的干支
        if ("身强".equals(getBodyIntensity())) {
            // 1.1、判断日元（日干）与年干的五行生克关系
            if ("身弱".equals(shengKe.get(getDayGan() + getYearGan()))) set.add(ganWuXing.get(getYearGan())); // 添加年干五行
            // 1.2、判断日元（日干）与年支的五行生克关系
            if ("身弱".equals(shengKe.get(getDayGan() + getYearZhi()))) set.add(zhiWuXing.get(getYearZhi())); // 添加年支五行
            // 1.3、判断日元（日干）与月干的五行生克关系
            if ("身弱".equals(shengKe.get(getDayGan() + getMonthGan()))) set.add(ganWuXing.get(getMonthGan())); // 添加月干五行
            // 1.4、判断日元（日干）与月支的五行生克关系
            if ("身弱".equals(shengKe.get(getDayGan() + getMonthZhi()))) set.add(zhiWuXing.get(getMonthZhi())); // 添加月支五行
            // 1.5、判断日元（日干）与日干的五行生克关系
            if ("身弱".equals(shengKe.get(getDayGan() + getDayGan()))) set.add(ganWuXing.get(getDayGan())); // 添加日干五行
            // 1.6、判断日元（日干）与日支的五行生克关系
            if ("身弱".equals(shengKe.get(getDayGan() + getDayZhi()))) set.add(zhiWuXing.get(getDayZhi())); // 添加日支五行
            // 1.7、判断日元（日干）与时干的五行生克关系
            if ("身弱".equals(shengKe.get(getDayGan() + getHourGan()))) set.add(ganWuXing.get(getHourGan())); // 添加时干五行
            // 1.8、判断日元（日干）与时支的五行生克关系
            if ("身弱".equals(shengKe.get(getDayGan() + getHourZhi()))) set.add(zhiWuXing.get(getHourZhi())); // 添加时支五行
            this.xiYongShen = new ArrayList<>(set);
            return;
        }

        // 2、若身弱，则寻找：同我、生我的干支
        if ("身弱".equals(getBodyIntensity())) {
            // 2.1、判断日元（日干）与年干的五行生克关系
            if ("身强".equals(shengKe.get(getDayGan() + getYearGan()))) set.add(ganWuXing.get(getYearGan())); // 添加年干的五行
            // 2.2、判断日元（日干）与年支的五行生克关系
            if ("身强".equals(shengKe.get(getDayGan() + getYearZhi()))) set.add(zhiWuXing.get(getYearZhi())); // 添加年支的五行
            // 2.3、判断日元（日干）与月干的五行生克关系
            if ("身强".equals(shengKe.get(getDayGan() + getMonthGan()))) set.add(ganWuXing.get(getMonthGan())); // 添加月干的五行
            // 2.4、判断日元（日干）与月支的五行生克关系
            if ("身强".equals(shengKe.get(getDayGan() + getMonthZhi()))) set.add(zhiWuXing.get(getMonthZhi())); // 添加月支的五行
            // 2.5、判断日元（日干）与日干的五行生克关系
            if ("身强".equals(shengKe.get(getDayGan() + getDayGan()))) set.add(ganWuXing.get(getDayGan())); // 添加日干五行
            // 2.6、判断日元（日干）与日支的五行生克关系
            if ("身强".equals(shengKe.get(getDayGan() + getDayZhi()))) set.add(zhiWuXing.get(getDayZhi())); // 添加日支的五行
            // 2.7、判断日元（日干）与时干的五行生克关系
            if ("身强".equals(shengKe.get(getDayGan() + getHourGan()))) set.add(ganWuXing.get(getHourGan())); // 添加时干的五行
            // 2.8、判断日元（日干）与时支的五行生克关系
            if ("身强".equals(shengKe.get(getDayGan() + getHourZhi()))) set.add(zhiWuXing.get(getHourZhi())); // 添加时支的五行
            this.xiYongShen = new ArrayList<>(set);
            return;
        }

        // 3、若身体为平衡或接近平衡，则使用具体法获取喜用神
        String season = getLunar().getSeason().substring(1, 2); // 获取季节简称（如：春）
        int lunarMonth = getLunar().getMonth(); // 农历月
        if (lunarMonth == 3 || lunarMonth == 6 || lunarMonth == 9 || lunarMonth == 12) season = "四季末";
        Map<String, List<String>> map = BaZiMap.XI_YONG_SHEN; // 具体法获取喜用神（天干+季节为键）
        this.xiYongShen = map.get(getDayGan() + season);

    }

    /**
     * 计算喜用神方位
     */
    private void xiYongShenFangWei() {

        List<String> list = new ArrayList<>();
        Map<String, List<String>> wuXingFangWei = BaZiMap.WU_XING_FANG_WEI; // 五行对应方位
        for (int i = 0; i < getXiYongShen().size(); i++) {
            String xiYongShen = getXiYongShen().get(i); // 每一个喜用神的方位
            List<String> xiYongFangWei = wuXingFangWei.get(xiYongShen);
            list.addAll(xiYongFangWei); // 保存所有喜用神的方位
        }
        this.xiYongShenFangWei = list;

    }

    /**
     * 计算骨重
     */
    private void guZhong() {

        int yearGuZhong = BaZiMap.YEAR_GU_ZHONG.get(getYearGanZhi()); // 出生年骨重
        int monthGuZhong = BaZiMap.MONTH_GU_ZHONG.get(getMonthZhi()); // 出生月骨重
        int dayGuZhong = BaZiMap.DAY_GU_ZHONG.get(getLunar().getDayInChinese()); // 出生日骨重
        int hourGuZhong = BaZiMap.HOUR_GU_ZHONG.get(getHourZhi()); // 出生时辰骨重

        int guZhong = yearGuZhong + monthGuZhong + dayGuZhong + hourGuZhong; // 骨重
        guZhong = Math.max(guZhong, 21); // 最轻骨重

        // 1、男命
        if ("男".equals(getSex())) {
            guZhong = Math.min(guZhong, 72); // 男命的最重骨重
            Map<Integer, String> yunChengWan = BaZiMap.YUN_CHENG_WAN; // 骨重批注（男命）
            this.guZhong = guZhongCharacters(guZhong); // 骨重
            this.guZhongPiZhu = yunChengWan.get(guZhong); // 骨重批注
        } else {
            // 2、女命
            guZhong = Math.min(guZhong, 71); // 女命的最重骨重
            Map<Integer, String> yunChengWan = BaZiMap.YUN_CHENG_WOMAN; // 骨重批注（女命）
            this.guZhong = guZhongCharacters(guZhong); // 骨重
            this.guZhongPiZhu = yunChengWan.get(guZhong); // 骨重批注
        }

    }

    /**
     * 计算日柱论命
     */
    private void dayZhuLunMing() {

        Map<String, String> lunMing = BaZiMap.DAY_ZHU_LUN_MING; // 日柱论命（日柱为键）
        this.dayZhuLunMing = lunMing.get(getDayGanZhi());

    }

    /**
     * 计算姻缘
     */
    private void yinYuan() {

        Map<String, String> map = BaZiMap.YIN_YUAN; // 姻缘（日干支纳音+农历月份为键）

        String dayGanZhiNaYin = getDayGanZhiNaYin().substring(2, 3); // 日干支纳音（如：木）
        int lunarMonth = getLunar().getMonth(); // 农历月份
        if (lunarMonth < 0) lunarMonth = -lunarMonth; // 月份若为负数则转为正数

        this.yinYuan = map.get(dayGanZhiNaYin + lunarMonth);

    }

    /**
     * 计算五行分析
     */
    private void wuXingFenXi() {

        String yearGanZhiNaYin = getYearGanZhiNaYin().substring(2, 3); // 年干支纳音（如：木）
        Map<String, String> wuXingFenXi = BaZiMap.WU_XING_FEN_XI; // 五行分析（根据年柱纳音五行计算）
        this.wuXingFenXi = "命主生于" + getYearGanZhi() + "年为" + getYearGanZhiNaYin() + "命，" + wuXingFenXi.get(yearGanZhiNaYin);

    }

    /**
     * 计算运势分析
     */
    public void yunShiFenXi() {

        Map<String, String> yunShiFenXi = BaZiMap.YUN_SHI_FEN_XI; // 运势分析（地支为键）
        this.yunShiFenXi = yunShiFenXi.get(getHourZhi());

    }

    /**
     * 计算性格分析
     */
    public void xingGeFenXi() {

        Map<String, String> xianTianXingGeFenXiMap = BaZiMap.XIAN_TIAN_XING_GE_FEN_XI; // 性格分析 - 先天性格（日干为键）
        Map<String, String> qianZaiXingGeFenXiMap = BaZiMap.QIAN_ZAI_XING_GE_FEN_XI; // 性格分析 - 潜在性格（五行为键）
        Map<String, String> waiXianXingGeFenXiMap = BaZiMap.WAI_XIAN_XING_GE_FEN_XI; // 性格分析 - 外显性格（十神为键）

        // 1.1、计算先天性格
        this.xianTianXingGeFenXi = xianTianXingGeFenXiMap.get(dayGan);
        // 1.2、计算潜在性格
        this.qianZaiXingGeFenXi = qianZaiXingGeFenXiMap.get(getWuXingWangShuai().get(0).substring(0, 1));
        // 1.3、计算外显性格
        this.waiXianXingGeFenXi = waiXianXingGeFenXiMap.get(getYearGanZhiZhuXing());

    }

    /**
     * 计算彭祖百忌
     */
    private void pengZuBaiJi() {

        this.pengZuBaiJi = getLunar().getPengZuGan() + "，" + getLunar().getPengZuZhi() + "。";

    }

    /**
     * 计算年太岁、月太岁、日太岁
     *
     * @param setting 八字-设置
     */
    private void taiSui(BaZiSetting setting) {

        Map<String, String> luoGong = BaZiMap.HOU_TIAN_BA_GUA_LUO_GONG; // 后天八卦落宫（八卦为键）

        // 1、计算年太岁
        String yearTaiSuiFangWei = getLunar().getYearPositionTaiSuiDesc(setting.getYearGanZhiSet() + 1); // 年太岁方位
        String yearTaiSuiLuoGong = getLunar().getYearPositionTaiSui(setting.getYearGanZhiSet() + 1); // 年太岁落宫
        this.yearTaiSui = "位于在" + yearTaiSuiFangWei + "方，落" + yearTaiSuiLuoGong + luoGong.get(yearTaiSuiLuoGong) + "宫。";

        // 2、计算月太岁
        String monthTaiSuiFangWei = getLunar().getMonthPositionTaiSuiDesc(setting.getYearGanZhiSet() + 1); // 月太岁方位
        String monthTaiSuiLuoGong = getLunar().getMonthPositionTaiSui(setting.getYearGanZhiSet() + 1); // 月太岁落宫
        this.monthTaiSui = "位于在" + monthTaiSuiFangWei + "方，落" + monthTaiSuiLuoGong + luoGong.get(monthTaiSuiLuoGong) + "宫。";

        // 3、计算日太岁
        String dayTaiSuiFangWei = getLunar().getDayPositionTaiSuiDesc(setting.getYearGanZhiSet() + 1); // 日太岁方位
        String dayTaiSuiLuoGong = getLunar().getDayPositionTaiSui(setting.getYearGanZhiSet() + 1); // 日太岁落宫
        this.dayTaiSui = "位于在" + dayTaiSuiFangWei + "方，落" + dayTaiSuiLuoGong + luoGong.get(dayTaiSuiLuoGong) + "宫。";

    }

    /**
     * 计算值日神（日喜神、日福神、日财神、日阳贵神、日阴贵神），值时神（时喜神、时福神、时财神、时阳贵神、时阴贵神）
     */
    private void shen() {

        Map<String, String> luoGong = BaZiMap.HOU_TIAN_BA_GUA_LUO_GONG; // 后天八卦落宫（八卦为键）

        // 1.1、计算日喜神
        String dayXiShenFangWei = getLunar().getDayPositionXiDesc(); // 日喜神方位
        String dayXiShenLuoGong = getLunar().getDayPositionXi(); // 日喜神落宫
        this.dayXiShen = "位于在" + dayXiShenFangWei + "方，落" + dayXiShenLuoGong + luoGong.get(dayXiShenLuoGong) + "宫。";

        // 1.2、计算日福神
        String dayFuShenFangWei = getLunar().getDayPositionFuDesc(); // 日福神方位
        String dayFuShenLuoGong = getLunar().getDayPositionFu(); // 日福神落宫
        this.dayFuShen = "位于在" + dayFuShenFangWei + "方，落" + dayFuShenLuoGong + luoGong.get(dayFuShenLuoGong) + "宫。";

        // 1.3、计算日财神
        String dayCaiShenFangWei = getLunar().getDayPositionCaiDesc(); // 日财神方位
        String dayCaiShenLuoGong = getLunar().getDayPositionCai(); // 日财神落宫
        this.dayCaiShen = "位于在" + dayCaiShenFangWei + "方，落" + dayCaiShenLuoGong + luoGong.get(dayCaiShenLuoGong) + "宫。";

        // 1.4、计算日阳贵神
        String dayYangGuiShenFangWei = getLunar().getDayPositionYangGuiDesc(); // 日阳贵神方位
        String dayYangGuiShenLuoGong = getLunar().getDayPositionYangGui(); // 日阳贵神落宫
        this.dayYangGuiShen = "位于在" + dayYangGuiShenFangWei + "方，落" + dayYangGuiShenLuoGong + luoGong.get(dayYangGuiShenLuoGong) + "宫。";

        // 1.5、计算日阴贵神
        String dayYinGuiShenFangWei = getLunar().getDayPositionYinGuiDesc(); // 日阴贵神方位
        String dayYinGuiShenLuoGong = getLunar().getDayPositionYinGui(); // 日阴贵神落宫
        this.dayYinGuiShen = "位于在" + dayYinGuiShenFangWei + "方，落" + dayYinGuiShenLuoGong + luoGong.get(dayYinGuiShenLuoGong) + "宫。";

        // 2.1、计算时喜神
        String hourXiShenFangWei = getLunar().getTimePositionXiDesc(); // 时喜神方位
        String hourXiShenLuoGong = getLunar().getTimePositionXi(); // 时喜神落宫
        this.hourXiShen = "位于在" + hourXiShenFangWei + "方，落" + hourXiShenLuoGong + luoGong.get(hourXiShenLuoGong) + "宫。";

        // 2.2、计算时福神
        String hourFuShenFangWei = getLunar().getTimePositionFuDesc(); // 时福神方位
        String hourFuShenLuoGong = getLunar().getTimePositionFu(); // 时福神落宫
        this.hourFuShen = "位于在" + hourFuShenFangWei + "方，落" + hourFuShenLuoGong + luoGong.get(hourFuShenLuoGong) + "宫。";

        // 2.3、计算时财神
        String hourCaiShenFangWei = getLunar().getTimePositionCaiDesc(); // 时财神方位
        String hourCaiShenLuoGong = getLunar().getTimePositionCai(); // 时财神落宫
        this.hourCaiShen = "位于在" + hourCaiShenFangWei + "方，落" + hourCaiShenLuoGong + luoGong.get(hourCaiShenLuoGong) + "宫。";

        // 2.4、计算时阳贵神
        String hourYangGuiShenFangWei = getLunar().getTimePositionYangGuiDesc(); // 时阳贵神方位
        String hourYangGuiShenLuoGong = getLunar().getTimePositionYangGui(); // 时阳贵神落宫
        this.hourYangGuiShen = "位于在" + hourYangGuiShenFangWei + "方，落" + hourYangGuiShenLuoGong + luoGong.get(hourYangGuiShenLuoGong) + "宫。";

        // 2.5、计算时阴贵神
        String hourYinGuiShenFangWei = getLunar().getTimePositionYinGuiDesc(); // 时阴贵神方位
        String hourYinGuiShenLuoGong = getLunar().getTimePositionYinGui(); // 时阴贵神落宫
        this.hourYinGuiShen = "位于在" + hourYinGuiShenFangWei + "方，落" + hourYinGuiShenLuoGong + luoGong.get(hourYinGuiShenLuoGong) + "宫。";

    }

    /**
     * 计算值日天神、值时天神
     */
    private void zhiTianShen() {

        // 1、计算值日天神
        String zhiRiTianShen = getLunar().getDayTianShen(); // 值日天神
        String zhiRiTianShenType = getLunar().getDayTianShenType(); // 值日天神类型
        String zhiRiTianShenLuck = getLunar().getDayTianShenLuck(); // 值日天神吉凶
        this.zhiDayTianShen = zhiRiTianShen + "（" + zhiRiTianShenType + "、" + zhiRiTianShenLuck + "）";

        // 2、计算值时天神
        String zhiShiTianShen = getLunar().getTimeTianShen(); // 值时天神
        String zhiShiTianShenType = getLunar().getTimeTianShenType(); // 值时天神类型
        String zhiShiTianShenLuck = getLunar().getTimeTianShenLuck(); // 值时天神吉凶
        this.zhiHourTianShen = zhiShiTianShen + "（" + zhiShiTianShenType + "、" + zhiShiTianShenLuck + "）";

    }

    /**
     * 计算逐月胎神、逐日胎神
     */
    private void zhuTaiShen() {

        // 1、计算逐月胎神
        this.zhuMonthTaiShen = getLunar().getMonthPositionTai();

        // 2、计算逐日胎神
        this.zhuDayTaiShen = getLunar().getDayPositionTai();

    }

    /**
     * 计算日宜忌（日宜、日忌、日吉神、日凶煞、日煞方位、日冲），时宜忌（时宜、时忌、时煞方位、时冲）
     */
    private void yiJi(BaZiSetting setting) {

        // 1、计算日宜忌（日宜、日忌、日吉神、日凶煞、日煞方位、日冲）
        this.dayYi = getLunar().getDayYi(setting.getMonthGanZhiSet() + 1); // 日宜
        this.dayJi = getLunar().getDayJi(setting.getMonthGanZhiSet() + 1); // 日忌
        this.dayJiShen = getLunar().getDayJiShen(); // 日吉神
        this.dayXiongSha = getLunar().getDayXiongSha(); // 日凶煞
        this.dayShaFangWei = getLunar().getDaySha() + "方"; // 日煞方位
        this.dayChong = getLunar().getDayChongShengXiao() + "（" + getLunar().getDayChongGan() + getLunar().getDayChong() + "）"; // 日冲

        // 2、计算时宜忌（时宜、时忌、时煞方位、时冲）
        this.hourYi = getLunar().getTimeYi(); // 时宜
        this.hourJi = getLunar().getTimeJi(); // 时忌
        this.hourShaFangWei = getLunar().getTimeSha() + "方"; // 时煞方位
        this.hourChong = getLunar().getTimeChongShengXiao() + "（" + getLunar().getTimeChongGan() + getLunar().getTimeChong() + "）"; // 时冲

    }

    /**
     * 计算值年九星、值月九星、值日九星、值时九星
     *
     * @param setting 八字-设置
     */
    private void jiuXing(BaZiSetting setting) {

        Map<String, String> jiuXing = BaZiMap.JIU_XING; // 数字对应九星（数字为键）

        // 1、计算值年九星
        String yearNumber = getLunar().getYearNineStar(setting.getYearGanZhiSet() + 1).toString().substring(0, 1);
        this.zhiYearJiuXing = jiuXing.get(yearNumber);

        // 2、计算值月九星
        String monthNumber = getLunar().getMonthNineStar(setting.getYearGanZhiSet() + 1).toString().substring(0, 1);
        this.zhiMonthJiuXing = jiuXing.get(monthNumber);

        // 3、计算值日九星
        String dayNumber = getLunar().getDayNineStar().toString().substring(0, 1);
        this.zhiDayJiuXing = jiuXing.get(dayNumber);

        // 4、计算值时九星
        String hourNumber = getLunar().getTimeNineStar().toString().substring(0, 1);
        this.zhiHourJiuXing = jiuXing.get(hourNumber);

    }

    /**
     * 计算大运及大运十神
     *
     * @param setting 八字-设置
     */
    private DaYun[] daYun(BaZiSetting setting) {

        EightChar eightChar = getLunar().getEightChar();

        // 初始化运
        Yun yun = eightChar.getYun(setting.getSex(), setting.getQiYunLiuPai());

        List<List<String>> daYunList = new ArrayList<>(); // 大运
        List<List<String>> daYunShiShenList = new ArrayList<>(); // 大运十神

        // 获取指定轮数的大运
        DaYun[] daYun = yun.getDaYun(setting.getDaYunLunSet()); // 默认获取10轮大运，也可传入指定轮数大运
        for (DaYun key : daYun) {
            // 添加大运
            daYunList.add(new ArrayList<>(Arrays.asList(String.valueOf(key.getStartYear()), String.valueOf(key.getStartAge()), key.getGanZhi())));
            // 添加大运十神
            if (!"".equals(key.getGanZhi())) {
                List<String> shiShen = getShiShen(key.getGanZhi());
                daYunShiShenList.add(shiShen);
            } else {
                daYunShiShenList.add(Arrays.asList("", ""));
            }
        }

        this.daYun = daYunList; // 大运
        this.daYunShiShen = daYunShiShenList; // 大运十神

        return daYun;

    }

    /**
     * 计算流年及流年十神
     *
     * @param daYun 大运
     */
    private void liuNian(DaYun[] daYun) {

        List<List<String>> liuNianList = new ArrayList<>(); // 流年
        List<List<String>> liuNianShiShenList = new ArrayList<>(); // 流年十神

        LiuNian[] liuNian;

        // 遍历大运
        for (DaYun key : daYun) {
            // 获取10轮流年
            liuNian = key.getLiuNian(10);
            for (LiuNian ln : liuNian) {
                // 添加流年
                liuNianList.add(new ArrayList<>(Arrays.asList(String.valueOf(ln.getYear()), String.valueOf(ln.getAge()), ln.getGanZhi())));
                // 添加流年十神
                List<String> shiShen = getShiShen(ln.getGanZhi());
                liuNianShiShenList.add(shiShen);
            }
        }

        this.liuNian = liuNianList; // 流年
        this.liuNianShiShen = liuNianShiShenList; // 流年十神

    }

//------------------------------------------------------------------------------------------------------------------------------------

    /**
     * 获取公历日期
     *
     * @return 公历日期
     */
    public String getSolarStr() {
        return CommonUtil.solarStr(getSolar());
    }

    /**
     * 获取农历日期
     *
     * @return 农历日期
     */
    public String getLunarStr() {
        return CommonUtil.lunarStr(getLunar());
    }

    /**
     * 添加同党或异党
     *
     * @param wuXingTongYi 以日干五行和其余干支五行获取同党或异党
     * @param dayGanWx     日干五行
     * @param ganOrZhiWx   天干五行或地支五行
     */
    protected void addTongYiDang(Map<String, String> wuXingTongYi, String dayGanWx, String ganOrZhiWx) {

        String tongOrYi = wuXingTongYi.get(dayGanWx + ganOrZhiWx);

        if ("同党".equals(tongOrYi)) {
            this.tongDangCount = getTongDangCount() + 1; // 同党数量
        } else {
            this.yiDangCount = getYiDangCount() + 1; // 异党数量
        }


    }

    /**
     * 判断干支五行并添加数量（不包含地支藏干）
     *
     * @param wuXing 干支五行
     */
    protected void isWuXing(String wuXing) {

        if ("木".equals(wuXing)) {
            this.muCount++;
        } else if ("火".equals(wuXing)) {
            this.huoCount++;
        } else if ("土".equals(wuXing)) {
            this.tuCount++;
        } else if ("金".equals(wuXing)) {
            this.jinCount++;
        } else if ("水".equals(wuXing)) {
            this.shuiCount++;
        }

    }

    /**
     * 判断干支五行并添加数量（包含地支藏干）
     *
     * @param wuXing 干支五行
     */
    protected void isZhiWuXing(String wuXing) {

        if ("木".equals(wuXing)) {
            this.muZhiCount++;
        } else if ("火".equals(wuXing)) {
            this.huoZhiCount++;
        } else if ("土".equals(wuXing)) {
            this.tuZhiCount++;
        } else if ("金".equals(wuXing)) {
            this.jinZhiCount++;
        } else if ("水".equals(wuXing)) {
            this.shuiZhiCount++;
        }

    }

    /**
     * 返回加分
     *
     * @param shengKe   天干和干支五行的生克关系
     * @param ganOrZhi1 天干或地支
     * @param ganOrZhi2 天干或地支
     * @param jia       加分
     * @return 加分
     */
    private int jiaFen(Map<String, String> shengKe, String ganOrZhi1, String ganOrZhi2, int jia) {

        int fen = 0;

        String qiangOrRuo = shengKe.get(ganOrZhi1 + ganOrZhi2); // '身强'或'身弱'
        // 若身强则加分
        if ("身强".equals(qiangOrRuo)) {
            fen += jia;
        }

        return fen;

    }

    /**
     * 骨重转为文字
     *
     * @param guZhong 骨重
     * @return 骨重文字
     */
    private String guZhongCharacters(Integer guZhong) {

        long liang = Long.parseLong(guZhong.toString().substring(0, 1)); // 两重
        long qian = Long.parseLong(guZhong.toString().substring(1, 2)); // 钱重

        String newGuZhong = CommonUtil.shuToHan(liang) + "两";
        if (0 != qian) {
            newGuZhong += CommonUtil.shuToHan(qian) + "钱";
        }

        return newGuZhong;

    }

    /**
     * 添加天干留意
     *
     * @param set 天干组合
     * @param map 天干相生、相合、相冲、相克
     */
    private void saveTianGanLiuYi(Set<String> set, Map<String, String> map) {

        set.add(map.get(getYearGan() + getMonthGan())); // 年干+月干
        set.add(map.get(getYearGan() + getDayGan()));   // 年干+日干
        set.add(map.get(getYearGan() + getHourGan()));  // 年干+时干
        set.add(map.get(getMonthGan() + getYearGan())); // 月干+年干
        set.add(map.get(getMonthGan() + getDayGan()));  // 月干+日干
        set.add(map.get(getMonthGan() + getHourGan())); // 月干+时干
        set.add(map.get(getDayGan() + getYearGan()));   // 日干+年干
        set.add(map.get(getDayGan() + getMonthGan()));  // 日干+月干
        set.add(map.get(getDayGan() + getHourGan()));   // 日干+时干
        set.add(map.get(getHourGan() + getYearGan()));  // 时干+年干
        set.add(map.get(getHourGan() + getMonthGan())); // 时干+月干
        set.add(map.get(getHourGan() + getDayGan()));   // 时干+日干

    }

    /**
     * 添加地支留意
     *
     * @param set 地支组合
     * @param map 地支半合、拱合、暗合、六合、相刑、相冲、相破、相害
     */
    private void saveDiZhiLiuYi(Set<String> set, Map<String, String> map) {

        set.add(map.get(getYearZhi() + getMonthZhi())); // 年支+月支
        set.add(map.get(getYearZhi() + getDayZhi()));   // 年支+日支
        set.add(map.get(getYearZhi() + getHourZhi()));  // 年支+时支
        set.add(map.get(getMonthZhi() + getYearZhi())); // 月支+年支
        set.add(map.get(getMonthZhi() + getDayZhi()));  // 月支+日支
        set.add(map.get(getMonthZhi() + getHourZhi())); // 月支+时支
        set.add(map.get(getDayZhi() + getYearZhi()));   // 日支+年支
        set.add(map.get(getDayZhi() + getMonthZhi()));  // 日支+月支
        set.add(map.get(getDayZhi() + getHourZhi()));   // 日支+时支
        set.add(map.get(getHourZhi() + getYearZhi()));  // 时支+年支
        set.add(map.get(getHourZhi() + getMonthZhi())); // 时支+月支
        set.add(map.get(getHourZhi() + getDayZhi()));   // 时支+日支

    }

    /**
     * 添加地支留意
     *
     * @param set 地支组合
     * @param map 地支三合、三刑
     */
    private void saveDiZhiLiuYi2(Set<String> set, Map<String, String> map) {

        set.add(map.get(getYearZhi() + getMonthZhi() + getDayZhi()));  // 年支+月支+日支
        set.add(map.get(getYearZhi() + getMonthZhi() + getHourZhi())); // 年支+月支+时支
        set.add(map.get(getYearZhi() + getDayZhi() + getMonthZhi()));  // 年支+日支+月支
        set.add(map.get(getYearZhi() + getDayZhi() + getHourZhi()));   // 年支+日支+时支
        set.add(map.get(getYearZhi() + getHourZhi() + getMonthZhi())); // 年支+时支+月支
        set.add(map.get(getYearZhi() + getHourZhi() + getDayZhi()));   // 年支+时支+日支

        set.add(map.get(getMonthZhi() + getYearZhi() + getDayZhi()));  // 月支+年支+日支
        set.add(map.get(getMonthZhi() + getYearZhi() + getHourZhi())); // 月支+年支+时支
        set.add(map.get(getMonthZhi() + getDayZhi() + getYearZhi()));  // 月支+日支+年支
        set.add(map.get(getMonthZhi() + getDayZhi() + getHourZhi()));  // 月支+日支+时支
        set.add(map.get(getMonthZhi() + getHourZhi() + getYearZhi())); // 月支+时支+年支
        set.add(map.get(getMonthZhi() + getHourZhi() + getDayZhi()));  // 月支+时支+日支

        set.add(map.get(getDayZhi() + getYearZhi() + getMonthZhi())); // 日支+年支+月支
        set.add(map.get(getDayZhi() + getYearZhi() + getHourZhi()));  // 日支+年支+时支
        set.add(map.get(getDayZhi() + getMonthZhi() + getYearZhi())); // 日支+月支+年支
        set.add(map.get(getDayZhi() + getMonthZhi() + getHourZhi())); // 日支+月支+时支
        set.add(map.get(getDayZhi() + getHourZhi() + getYearZhi()));  // 日支+时支+年支
        set.add(map.get(getDayZhi() + getHourZhi() + getMonthZhi())); // 日支+时支+月支

        set.add(map.get(getHourZhi() + getYearZhi() + getMonthZhi())); // 时支+年支+月支
        set.add(map.get(getHourZhi() + getYearZhi() + getDayZhi()));   // 时支+年支+日支
        set.add(map.get(getHourZhi() + getMonthZhi() + getYearZhi())); // 时支+月支+年支
        set.add(map.get(getHourZhi() + getMonthZhi() + getDayZhi()));  // 时支+月支+日支
        set.add(map.get(getHourZhi() + getDayZhi() + getYearZhi()));   // 时支+日支+年支
        set.add(map.get(getHourZhi() + getDayZhi() + getMonthZhi()));  // 时支+日支+月支

    }

    /**
     * 返回十神
     *
     * @param ganZhi 干支
     * @return 十神
     */
    private List<String> getShiShen(String ganZhi) {

        List<String> shiShen = new ArrayList<>();
        Map<String, String> shiShenMap = BaZiMap.SHI_SHEN_MING_PAN_MAP; // 十神，用于命盘（日干+其他干支为键）

        String gan = ganZhi.substring(0, 1); // 天干
        String zhi = ganZhi.substring(1, 2); // 地支
        String ganShiShen = shiShenMap.get(getDayGan() + gan); // 天干十神
        String zhiShiShen = shiShenMap.get(getDayGan() + zhi); // 地支十神
        shiShen.add(ganShiShen);
        shiShen.add(zhiShiShen);

        return shiShen;

    }

    /**
     * 判断并添加干支神煞是否带有太极贵人、天医、华盖、童子煞、十灵日
     *
     * @param ganZhiShenSha 干支神煞
     * @param shenShaList   神煞数据
     */
    private void addGanZhiShenSha(List<String> ganZhiShenSha, List<String> shenShaList) {

        for (String ss : ganZhiShenSha) {
            if ("太极贵人".equals(ss)) {
                shenShaList.add("太极贵人");
            }
            if ("童子煞".equals(ss)) {
                shenShaList.add("童子煞");
            }
            if ("十灵日".equals(ss)) {
                shenShaList.add("十灵日");
            }
            if ("天医".equals(ss)) {
                shenShaList.add("天医");
            }
            if ("华盖".equals(ss)) {
                shenShaList.add("华盖");
            }
        }

    }

    /**
     * 判断并返回天数或地数
     *
     * @param tianDiShu 天数或地数
     * @param base      基数（天数的基数取25。地数的基数取30）
     * @param quShu     取数（天数取5。地数取3）
     * @return 天数或地数
     */
    private int isTianDiShu(int tianDiShu, int base, int quShu) {

        if (tianDiShu > base) {
            // 2.1、若天数或地数大于25\30，则减去25\30，若仍大于10，则减去10，取个位数
            tianDiShu -= base;
            do {
                if (tianDiShu > 10) {
                    tianDiShu -= 10;
                } else if (tianDiShu == 10) {
                    tianDiShu = 1;
                }
            } while (tianDiShu >= 10);
        } else if (tianDiShu == base) {
            // 2.2、若天数或地数等于25\30，则取5\3
            tianDiShu = quShu;
        } else {
            if (tianDiShu == 10 || tianDiShu == 20) {
                // 2.3、若天数或地数小于25\30，并且个位数为0时，取十位数
                if (tianDiShu == 10) {
                    tianDiShu = 1;
                } else {
                    tianDiShu = 2;
                }
            } else {
                // 2.4、若天数或地数小于25\30，并且个位数不为0时，取个位数
                if (tianDiShu > 10) {
                    tianDiShu = Integer.parseInt(String.valueOf(tianDiShu).substring(1, 2));
                } else {
                    tianDiShu = Integer.parseInt(String.valueOf(tianDiShu).substring(0, 1));
                }
            }
        }

        return tianDiShu;

    }

    /**
     * 根据三元和性别寄卦并返回天数或地数
     *
     * @param ganYinYang 天干阴阳
     * @param tianDiShu  天数或地数
     * @param sanYuan    三元
     * @return 天数或地数
     */
    private int getTianDiShu(Map<String, String> ganYinYang, int tianDiShu, String sanYuan) {

        // 1、上元：男寄艮卦、女寄坤卦（艮卦数字为8，坤卦数字为2）
        if ("上元".equals(sanYuan)) {
            tianDiShu = "男".equals(getSex()) ? 8 : 2;
        }

        // 2、中元：阳男阴女寄艮卦、阴男阳女寄坤卦（艮卦数字为8，坤卦数字为2）
        if ("中元".equals(sanYuan)) {
            if ("阳".equals(ganYinYang.get(getYearGan())) && "男".equals(getSex())) tianDiShu = 8; // 阳男，寄艮卦
            if ("阴".equals(ganYinYang.get(getYearGan())) && "女".equals(getSex())) tianDiShu = 8; // 阴女，寄艮卦
            if ("阴".equals(ganYinYang.get(getYearGan())) && "男".equals(getSex())) tianDiShu = 2; // 阴男，寄坤卦
            if ("阳".equals(ganYinYang.get(getYearGan())) && "女".equals(getSex())) tianDiShu = 2; // 阳女，寄坤卦
        }

        // 3、下元：男寄离卦、女寄兑卦（离卦数字为9，兑卦数字为7）
        if ("下元".equals(sanYuan)) {
            tianDiShu = "男".equals(getSex()) ? 9 : 7;
        }

        return tianDiShu;

    }


}
